#include <asm/uaccess.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>

static char* filename = "/home/ngx/code/test/test.txt";

void file_read(const char* filename)
{
    struct file* filp;
    mm_segment_t fs;
    off_t        fsize;
    char*        buf = NULL;

    printk("<1>start....\n");
    filp = filp_open(filename, O_RDONLY, 0666);
    if (IS_ERR(filp)) {
        printk("open error...\n");
        return;
    }

    fsize = i_size_read(filp->f_inode);
    if (fsize <= 0) return;
    buf = (char*)kcalloc(fsize + 1, 1, GFP_KERNEL);
    if (!buf) {
        printk("malloc failed.\n");
        return;
    }

    fs = get_fs();
    set_fs(KERNEL_DS);
    printk("<1>read to buf ...\n");
    vfs_read(filp, buf, fsize, &(filp->f_pos));
    set_fs(fs);

    buf[fsize] = '\0';
    printk("<1>The File Content is:\n");
    printk("%s\n", buf);

    kfree(buf);
    filp_close(filp, NULL);
}

void file_write(char* filename, char* data)
{
    struct file* filp;
    mm_segment_t fs;
    filp = filp_open(filename, O_RDWR | O_APPEND, 0666);
    if (IS_ERR(filp)) {
        printk("open error...\n");
        return;
    }
    fs = get_fs();
    set_fs(KERNEL_DS);
    vfs_write(filp, data, strlen(data), &filp->f_pos);
    set_fs(fs);
    filp_close(filp, NULL);
}

static int hello_init(void)
{
    printk("<1>Read File from Kernel.\n");
    file_read(filename);
    file_write(filename, "kernel write test\n");
    return 0;
}

static void hello_cleanup(void) { printk("byebye module.\n"); }

module_init(hello_init);
module_exit(hello_cleanup);
MODULE_LICENSE("GPL");
